#include "napi/native_api.h"
#include "stb/stb_image_resize.h"
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <ostream>
#include <string>

void log(const std::string& message) {
    std::cout << "[LOG] " << message << std::endl;
}

static napi_value ResizeImage(napi_env env, napi_callback_info info) {
    size_t argc = 7;
    napi_value args[7] = {nullptr};

    // 获取回调参数
    napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get callback info");
        return nullptr;
    }

    // 参数检查
    if (argc < 7) {
        napi_throw_error(env, nullptr, "Wrong number of arguments");
        return nullptr;
    }

    // 获取输入像素数据
    void* input_pixels;
    size_t input_pixels_length;
    napi_typedarray_type input_type;
    status = napi_get_typedarray_info(env, args[0], &input_type, &input_pixels_length, 
                                     &input_pixels, nullptr, nullptr);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get input pixels info");
        return nullptr;
    }
    
     // 检查输入类型是否为Uint8Array
    if (input_type != napi_uint8_array) {
        napi_throw_error(env, nullptr, "inputPixels must be a Uint8Array");
        return nullptr;
    }
    
    
    // 获取输入宽高
    int32_t input_w, input_h;
    status = napi_get_value_int32(env, args[1], &input_w);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get inputW");
        return nullptr;
    }
    
    status = napi_get_value_int32(env, args[2], &input_h);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get inputH");
        return nullptr;
    }
    
     // 获取输出宽高
    int32_t output_w, output_h;
    status = napi_get_value_int32(env, args[3], &output_w);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get outputW");
        return nullptr;
    }
    
    status = napi_get_value_int32(env, args[4], &output_h);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get outputH");
        return nullptr;
    }
    
    // 获取通道数和数据类型
    int32_t num_channels;
    status = napi_get_value_int32(env, args[5], &num_channels);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get numChannels");
        return nullptr;
    }

    int32_t datatype;
    status = napi_get_value_int32(env, args[6], &datatype);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to get datatype");
        return nullptr;
    }

    // 验证参数有效性
    if (input_w <= 0 || input_h <= 0 || output_w <= 0 || output_h <= 0 || 
        num_channels < 1 || num_channels > 4) {
        napi_throw_error(env, nullptr, "Invalid image parameters");
        return nullptr;
    }

    // 计算输入输出的跨度
    int input_stride_in_bytes = input_w * num_channels;
    int output_stride_in_bytes = output_w * num_channels;

    // 创建输出缓冲区
    size_t output_size = (size_t)(output_w * output_h * num_channels);
    void* output_pixels = malloc(output_size);

    if (output_pixels == nullptr) {
        napi_throw_error(env, nullptr, "Failed to allocate memory for output image");
        return nullptr;
    }

    // 执行图像缩放
    int result = 0;
    if (datatype == 0) {
        // 使用stbir_resize_uint8处理uint8类型
        result = stbir_resize_uint8(
            (const unsigned char*)input_pixels, input_w, input_h, input_stride_in_bytes,
            (unsigned char*)output_pixels, output_w, output_h, output_stride_in_bytes,
            num_channels
        );
    } else {
        // 处理其他数据类型
        result = stbir_resize(
            input_pixels, input_w, input_h, input_stride_in_bytes,
            output_pixels, output_w, output_h, output_stride_in_bytes,
            (stbir_datatype)datatype,
            num_channels, STBIR_ALPHA_CHANNEL_NONE, 0,
            STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP,
            STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
            STBIR_COLORSPACE_LINEAR, nullptr
        );
    }

    // 检查缩放是否成功
    if (result == 0) {
        free(output_pixels);
        napi_throw_error(env, nullptr, "Image resize failed");
        return nullptr;
    }
    
     // 创建返回的ArrayBuffer和Uint8Array
    napi_value array_buffer;
    void* buffer_ptr = nullptr;
    status = napi_create_arraybuffer(env, output_size, &buffer_ptr, &array_buffer);
    if (status != napi_ok || buffer_ptr == nullptr) {
        free(output_pixels);
        napi_throw_error(env, nullptr, "Failed to create array buffer");
        return nullptr;
    }

    // 拷贝数据到ArrayBuffer
    memcpy(buffer_ptr, output_pixels, output_size);
    free(output_pixels);
    
    // 创建Uint8Array
    napi_value uint8_array;
    status = napi_create_typedarray(env, napi_uint8_array, output_size, array_buffer, 0, &uint8_array);
    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to create uint8 array");
        return nullptr;
    }
    return uint8_array;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        {.utf8name = "resizeImage",
         .name = nullptr,
         .method = ResizeImage,
         .getter = nullptr,
         .setter = nullptr,
         .value = nullptr,
         .attributes = napi_default,
         .data = nullptr}
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    
    
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
    napi_module_register(&demoModule);
}